package com.sleepcamel.resteasyConfigurator.view;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.forms.widgets.FormToolkit;

import com.sleepcamel.resteasyConfigurator.components.wizard.DBConnectionWizard;
import com.sleepcamel.resteasyConfigurator.model.App;
import com.sleepcamel.resteasyConfigurator.util.FileUtils;

public class MainApp implements PropertyChangeListener {
	private static final String APP_TITLE = "RestEasy Configurator";
	protected Shell shlResteasyConfigurator;
	private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());
	private MenuItem mntmNewSubmenu;

	private MenuItem mntmNewSubmenu_3;
	
	protected App app = App.getInstance();
	private MainContainer mainContainer;
	private MenuItem mntmNewSubmenu_2;

	private MenuItem mntmLoad;

	private MenuItem mntmSave;

	private MenuItem mntmSaveAs;

	private MenuItem mntmClose;

	private MenuItem mntmGenerateToJava;
	private MenuItem projectFromDB;
	private MenuItem mntmImport;

	/**
	 * Launch the application.
	 * @param args
	 */
	public static void main(String[] args) {
		Display display = Display.getDefault();
		Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
			public void run() {
				MainApp window = new MainApp();
				window.open();
			}
		});
	}

	/**
	 * Open the window.
	 */
	public void open() {
		Display display = Display.getDefault();
		app.addPropertyChangeListener(this);
		createContents();
		app.setShell(shlResteasyConfigurator);
		shlResteasyConfigurator.open();
		shlResteasyConfigurator.layout();
		while (!shlResteasyConfigurator.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shlResteasyConfigurator = new Shell();
		shlResteasyConfigurator.setSize(820, 500);
		shlResteasyConfigurator.setText(APP_TITLE);
		shlResteasyConfigurator.setLayout(new FormLayout());
		
		Menu menu = new Menu(shlResteasyConfigurator, SWT.BAR);
		shlResteasyConfigurator.setMenuBar(menu);
		
		mntmNewSubmenu = new MenuItem(menu, SWT.CASCADE);
		mntmNewSubmenu.setText("&File");
		
		Menu menu_1 = new Menu(mntmNewSubmenu);
		mntmNewSubmenu.setMenu(menu_1);
		
		mntmNewSubmenu_3 = new MenuItem(menu_1, SWT.NONE);
		mntmNewSubmenu_3.setText("&New Project");
		mntmNewSubmenu_3.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				app.loadNewProject();
			}
		});
		
		mntmLoad = new MenuItem(menu_1, SWT.NONE);
		mntmLoad.setText("&Load");
		mntmLoad.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				app.loadProject(FileUtils.getFileToLoad(shlResteasyConfigurator));
			}

		});
		
		mntmSave = new MenuItem(menu_1, SWT.NONE);
		mntmSave.setText("&Save");
		mntmSave.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if ( app.isCurrentProjectLoaded() ){
					File file = app.getCurrentProjectFile();
					if ( file == null){
						file = FileUtils.getFileToSave(shlResteasyConfigurator);
					}
					app.saveProject(file);
					updateTitle();
				}
					
			}

		});
		
		mntmSaveAs = new MenuItem(menu_1, SWT.NONE);
		mntmSaveAs.setText("Save &As...");
		mntmSaveAs.addSelectionListener(new SelectionAdapter() {
			
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				if ( app.isCurrentProjectLoaded() ){
					app.saveProject(FileUtils.getFileToSave(shlResteasyConfigurator));
					updateTitle();
				}
			    
			}
		});
		
		mntmClose = new MenuItem(menu_1, SWT.NONE);
		mntmClose.setText("&Close");
		mntmClose.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				app.closeCurrentProject();
			}
		});
		
		new MenuItem(menu_1, SWT.SEPARATOR);
		
		mntmImport = new MenuItem(menu_1, SWT.CASCADE);
		mntmImport.setText("&Import");
		
		Menu menuImport = new Menu(mntmImport);
		mntmImport.setMenu(menuImport);

		projectFromDB = new MenuItem(menuImport, SWT.NONE);
		projectFromDB.setText("Generate from &DB Connection");
		projectFromDB.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				WizardDialog dlg = new WizardDialog(shlResteasyConfigurator,
						new DBConnectionWizard(app.getDBConnectionModel()));
				dlg.open();
			}
		});
		
		new MenuItem(menu_1, SWT.SEPARATOR);
		
		MenuItem mntmExit = new MenuItem(menu_1, SWT.NONE);
		mntmExit.setText("&Exit");
		mntmExit.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				shlResteasyConfigurator.dispose();
			}
		});
		
		MenuItem mntmNewSubmenu_1 = new MenuItem(menu, SWT.CASCADE);
		mntmNewSubmenu_1.setText("&Edit");
		
		Menu menu_2 = new Menu(mntmNewSubmenu_1);
		mntmNewSubmenu_1.setMenu(menu_2);
		
		MenuItem mntmNewItem_1 = new MenuItem(menu_2, SWT.NONE);
		mntmNewItem_1.setText("Cut");
		
		MenuItem mntmNewItem_2 = new MenuItem(menu_2, SWT.NONE);
		mntmNewItem_2.setText("Copy");
		
		MenuItem mntmNewItem_3 = new MenuItem(menu_2, SWT.NONE);
		mntmNewItem_3.setText("Paste");
		
		new MenuItem(menu_2, SWT.SEPARATOR);
		
		MenuItem mntmNewItem_4 = new MenuItem(menu_2, SWT.NONE);
		mntmNewItem_4.setText("&Preferences");
		
		MenuItem mntmProject = new MenuItem(menu, SWT.CASCADE);
		mntmProject.setText("&Project");
		
		Menu projectSubmenu = new Menu(mntmProject);
		mntmProject.setMenu(projectSubmenu);
		
		mntmGenerateToJava = new MenuItem(projectSubmenu, SWT.NONE);
		mntmGenerateToJava.setText("Generate &Java Files");
		mntmGenerateToJava.setEnabled(false);
		mntmGenerateToJava.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if ( app.isCurrentProjectLoaded() ){
					try {
						app.generateAndSaveSources(FileUtils.getDirectoryToSave(shlResteasyConfigurator, "Please provide directory where to save generated sources", app.getLastSavedDirectory()));
					} catch (IOException e1) {
						Status status = new Status(IStatus.ERROR, "My Plug-in ID", 0, e1.getMessage(), null);
						ErrorDialog.openError(shlResteasyConfigurator, "Generation Error", "We were not able to save generated sources", status);
					}
				}
			}
		});

		mntmNewSubmenu_2 = new MenuItem(menu, SWT.CASCADE);
		mntmNewSubmenu_2.setText("&Help");
		
		Menu menu_3 = new Menu(mntmNewSubmenu_2);
		mntmNewSubmenu_2.setMenu(menu_3);
		
		MenuItem mntmNewItem = new MenuItem(menu_3, SWT.NONE);
		mntmNewItem.setText("&About");
		
		mainContainer = new MainContainer(shlResteasyConfigurator, SWT.NONE);
		FormData fd_mainContainer = new FormData();
		fd_mainContainer.top = new FormAttachment(0);
		fd_mainContainer.right = new FormAttachment(100);
		fd_mainContainer.left = new FormAttachment(0);
		fd_mainContainer.bottom = new FormAttachment(100, -18);
		mainContainer.setLayoutData(fd_mainContainer);
		formToolkit.adapt(mainContainer);
		formToolkit.paintBordersFor(mainContainer);
		
		Label statusBar = formToolkit.createLabel(shlResteasyConfigurator, "", SWT.BORDER);
		FormData fd_lblNewLabel = new FormData();
		fd_lblNewLabel.height = 15;
		fd_lblNewLabel.bottom = new FormAttachment(100);
		fd_lblNewLabel.right = new FormAttachment(100);
		fd_lblNewLabel.left = new FormAttachment(0);
		statusBar.setLayoutData(fd_lblNewLabel);
		
		initDataBindings();
	}
	
	protected void updateTitle() {
		StringBuilder sb = new StringBuilder();
		sb.append(APP_TITLE);
		if ( app.isCurrentProjectLoaded() ){
			sb.append(" - ").append(app.getCurrentProject().getName());
			String currentProjectPath = app.currentProjectPath();
			if ( !currentProjectPath.isEmpty() ){
				sb.append(" (").append(currentProjectPath).append(")");
			}
		}
		shlResteasyConfigurator.setText(sb.toString());
	}

	protected void initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		IObservableValue mainContainerObserveVisibleObserveWidget = SWTObservables.observeVisible(mainContainer);
		IObservableValue appCurrentProjectLoadedObserveValue = BeansObservables.observeValue(app, "currentProjectLoaded");
		bindingContext.bindValue(mainContainerObserveVisibleObserveWidget, appCurrentProjectLoadedObserveValue, null, null);
		//
		IObservableValue closeEnabledObserveValue = BeansObservables.observeValue(mntmClose, "enabled");
		bindingContext.bindValue(closeEnabledObserveValue, appCurrentProjectLoadedObserveValue, null, null);
		
		IObservableValue saveEnabledObserveValue = BeansObservables.observeValue(mntmSave, "enabled");
		bindingContext.bindValue(saveEnabledObserveValue, appCurrentProjectLoadedObserveValue, null, null);
		
		IObservableValue saveAsEnabledObserveValue = BeansObservables.observeValue(mntmSaveAs, "enabled");
		bindingContext.bindValue(saveAsEnabledObserveValue, appCurrentProjectLoadedObserveValue, null, null);
		
		IObservableValue mntmGenerateEnabledObserveValue = BeansObservables.observeValue(mntmGenerateToJava, "enabled");
		bindingContext.bindValue(mntmGenerateEnabledObserveValue, appCurrentProjectLoadedObserveValue, null, null);
	}

	@Override
	public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
		if ( propertyChangeEvent.getSource().equals(app) && propertyChangeEvent.getPropertyName().equals("currentProject") ){
			mainContainer.refreshTree(true);
			updateTitle();			
		}
	}
}
